﻿using System;
using System.IO;
using System.Reflection;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xunit;

namespace Adjunct.Build.Tasks
{
	public class BindAdjunctPropertiesSpec
	{
		[Fact]
		public void HandleMultipleSpecFiles() {
			string projectPath = TestHelper.GetProjectDirectory();
			TaskItem[] specs = new[] { new TaskItem("package1.nuspec"), new TaskItem("package2.nuspec") };
			MockBuildEngine engine = new MockBuildEngine {
				ProjectFileOfTaskNode = Path.Combine(projectPath, "test.proj")
			};
			BindAdjunctProperties task = new BindAdjunctProperties {
				ProjectDirectory = projectPath,
				OutputPath = @"bin\Debug\",
				PackageSpecs = specs,
				BuildEngine = engine
			};
			task.Execute().ShouldBeFalse();
			TestHelper.Dump(engine.Log.ToString());
			task.NuGetOutputDirectory.ShouldEqual(GetExpectedOutputPath(projectPath));
			task.NuGetStagingFullDir.ShouldEqual(GetExpectedStagingPath(projectPath));
			task.NuspecSourceFullPath.ShouldEqual(string.Empty);
			task.NuspecStagedFullPath.ShouldEqual(string.Empty);
			task.PackagesDirectory.ShouldEqual(string.Empty);
			task.NuGetExe.ShouldEqual(string.Empty);
			XElement expectedLog = new XElement("Log",
			                                    new XElement("Info", "NuGetOutputDirectory: " + GetExpectedOutputPath(projectPath)),
			                                    new XElement("Info", @"NuGetStagingFullDir: " + GetExpectedStagingPath(projectPath)),
			                                    new XElement("Error", task.BuildMultipleSpecsErrorMessage()));
			engine.Log.ShouldEqual(expectedLog);
		}

		[Fact]
		public void HandleNoSpecFile() {
			string projectPath = TestHelper.GetProjectDirectory();
			MockBuildEngine engine = new MockBuildEngine {
				ProjectFileOfTaskNode = Path.Combine(projectPath, "test.proj")
			};
			BindAdjunctProperties task = new BindAdjunctProperties {
				ProjectDirectory = projectPath,
				OutputPath = @"bin\Debug",
				PackageSpecs = new ITaskItem[0],
				BuildEngine = engine
			};
			task.Execute().ShouldBeTrue();
			TestHelper.Dump(engine.Log.ToString());
			task.NuGetOutputDirectory.ShouldEqual(GetExpectedOutputPath(projectPath));
			task.NuGetStagingFullDir.ShouldEqual(GetExpectedStagingPath(projectPath));
			task.NuspecSourceFullPath.ShouldEqual(string.Empty);
			task.NuspecStagedFullPath.ShouldEqual(string.Empty);
			task.PackagesDirectory.ShouldEqual(string.Empty);
			task.NuGetExe.ShouldEqual(string.Empty);
		}

		[Fact]
		public void ProcessSingleSpec() {
			string projectPath = TestHelper.GetProjectDirectory();
			MockBuildEngine engine = new MockBuildEngine {
				ProjectFileOfTaskNode = Path.Combine(projectPath, "test.proj")
			};
			ITaskItem[] specs = new[] { new MockNuspecTaskItem(projectPath) };
			BindAdjunctProperties task = new BindAdjunctProperties {
				ProjectDirectory = projectPath,
				OutputPath = "bin\\Debug",
				PackageSpecs = specs,
				BuildEngine = engine
			};
			task.Execute().ShouldBeTrue();
			TestHelper.Dump(engine.Log.ToString());
			task.NuGetOutputDirectory.ShouldEqual(GetExpectedOutputPath(projectPath));
			task.NuGetStagingFullDir.ShouldEqual(GetExpectedStagingPath(projectPath));
			task.NuspecSourceFullPath.ShouldEqual(Path.Combine(projectPath, "test.nuspec"));
			task.NuspecStagedFullPath.ShouldEqual(Path.Combine(GetExpectedStagingPath(projectPath), "test.nuspec"));
			task.PackagesDirectory.ShouldEqual(GetExpectedPackagesPath(projectPath));
			task.NuGetExe.ShouldNotBeNull();
			task.NuGetExe.ShouldNotBeEmpty();
			task.NuGetExe.ShouldContain(task.PackagesDirectory);
			task.NuGetExe.ShouldContain(@"tools\NuGet.exe");
		}

		private string GetExpectedOutputPath(string projectPath) {
			return Path.Combine(projectPath, @"bin\Debug");
		}

		private string GetExpectedPackagesPath(string projectPath) {
			projectPath = Path.GetDirectoryName(projectPath); // Adjunct\Tools
			projectPath = Path.GetDirectoryName(projectPath); // Adjunct
			projectPath = Path.Combine(projectPath, "Packages"); // Adjunct\Packages
			return projectPath;
		}

		private string GetExpectedStagingPath(string projectPath) {
			return Path.Combine(projectPath, @"bin\Debug\NuGet");
		}
	}
}